#include "qrscserver.h"
#include <QBuffer>
#include <QGuiApplication>
#include <QWidget>
#include <QThread>
#include <QPushButton>
QRSCServer::QRSCServer(QObject *parent)
    :QTcpServer(parent)
    ,_caption(this)
    ,_control(nullptr)
    ,_quality(20)
{
    screenshot      = new AsyncScreenshot();
    port            = 54520;
    _caption.setInterval(50);
    _caption.setSingleShot(false);
    connect(&_caption,&QTimer::timeout,[this]{
        sendImage();
    });
}

QRSCServer::~QRSCServer()
{
    delete screenshot;
}

/**
 * @name    startServer
 * @brief   开启t服务器
 * @param   quality 画面质量 1~9
 * @return  void
*/
bool QRSCServer::startServer(int quality)
{
    if(listen(QHostAddress::Any,port)){
        _quality = quality*10;
        _caption.start();
        qDebug() << "server start...";
        return true;
    }
    return false;
}

/**
 * @name    stopServer
 * @brief   关闭服务器
 * @param   void
 * @return  void
*/
void QRSCServer::stopServer()
{
    _caption.stop();
    close();
    for (auto it = _clientscreen.begin(); it != _clientscreen.end(); ++it) {
        it.key()->deleteLater();
    }
    _clientscreen.clear();
    qDebug() << "server stop...";
    emit sigStopServer();
}

/**
 * @name    sendImage
 * @brief   采集桌面图片
 * @param   void
 * @return  void
*/
void QRSCServer::sendImage()
{
    static int num = 0;
    QHash<int, QByteArray> images;
    for (auto it = _clientscreen.begin(); it != _clientscreen.end(); ++it) {
        auto i = it.value();
        QTcpSocket* client = it.key();
        i.srceenIndex = qMax(i.srceenIndex - 1, 0);
        if(!images.contains(i.srceenIndex)){
            // 需要截图时
            screenshot->requestScreenshot();
            // 等待结果
            QEventLoop loop;
            connect(screenshot, &AsyncScreenshot::screenshotReady,
                    &loop, &QEventLoop::quit);
            loop.exec();
            QByteArray imageData;
            QBuffer buffer(&imageData);
            buffer.open(QIODevice::WriteOnly);
            screenshot->pixmap.save(&buffer, "JPEG", _quality);
            images[i.srceenIndex] = imageData;
        }
        //防止中途客户端 断开连接
        //这里数据头跟数据分开发送，等待接收表示再进行发送图像数据
        if(!i.sendFlag){
            if(_clientscreen.count() == 0 || !_clientscreen.contains(client)){
                qDebug()<<"客户端 断开";
                return;
            }
            QString sInfo = QString("packet:")+QString::number(++num)+";size:"+QString::number(images[i.srceenIndex].size());//qDebug()<<"sInfo="<<sInfo;
            client->write(sInfo.toLatin1());
        }else{
            _clientscreen[client].sendFlag = false;
            if(_clientscreen.count() == 0 || !_clientscreen.contains(client)){
                qDebug()<<"客户端 断开";
                return;
            }
            client->write(images[i.srceenIndex]);
        }
    }
    num %= 10000;
}

/**
 * @name    incomingConnection
 * @brief   新连接的套接字
 * @param   socketDescriptor 套接字描述符
 * @return  void
*/
void QRSCServer::incomingConnection(qintptr socketDescriptor)
{
    QTcpSocket *clientSocket = new QTcpSocket(this);
    clientSocket->setSocketDescriptor(socketDescriptor);
    qDebug() << "client connection:" << clientSocket->peerAddress().toString();
    _clientscreen[clientSocket] = ClientInfo();
    if(_control==nullptr){
        _control = clientSocket;
    }
    connect(clientSocket, &QTcpSocket::disconnected, [clientSocket,this]{
        qDebug() << "client disconnected:" << clientSocket->peerAddress().toString();
        QMetaObject::invokeMethod(this,[clientSocket,this]{
            if(clientSocket == _control){
                _control = nullptr;
            }
            this->_clientscreen.remove(clientSocket);
            clientSocket->deleteLater();
        });
    });

    connect(clientSocket, &QTcpSocket::readyRead, [clientSocket,this]{
        if(clientSocket == _control){
            QByteArray data = clientSocket->readAll();
            //qDebug() << data;
            _clientscreen[clientSocket].sendFlag = true;
            //move:100:100
            if(QString(data).startsWith("move:")){
                //qDebug()<<"readyRead="<<data;
                auto opt = QString(data).split(":");
                if(opt.count() == 3){
                    QPoint point;
                    point.setX(opt.at(1).toInt());
                    point.setY(opt.at(2).toInt());
                    screenshot->requestMoveMouse(point);
                }
            }
        }
    });
}
